/*
 * ImageLayout.cpp
 *
 *  Created on: 22.10.2012
 *      Author: caffeine
 */

#include "CompositeImage.h"
#include <Utils.h>

#include <log/Log.h>

ImageLayout*CompositeImage::add(irr::core::position2di position,irr::io::path path){
	ImageLayout*res=new ImageLayout(this);
	res->setPosition(position);
	res->setPath(path);
	add(res);
	res->drop();
	return res;
}

void CompositeImage::add(ImageLayout*layout){
	list.push_back(layout);
	layout->grab();
	changed=true;
}

ImageLayout*CompositeImage::get(irr::u32 index){
	return list[index];
}
irr::u32 CompositeImage::size(){
	return list.size();
}

void CompositeImage::setSize(irr::core::dimension2du size){
	load_mutex->lock();
	if (stage)
		stage->drop();
	stage=device->getVideoDriver()->createImage(irr::video::ECF_A8R8G8B8,Size);
	changed=true;
	load_mutex->unlock();
}

void CompositeImage::remove(irr::u32 index){
	list[index]->drop();
	list.erase(index);
	changed=true;
}

void CompositeImage::remove(ImageLayout*layout){
	irr::s32 index=indexOf(layout);
	if (index>=0)
		remove(index);
}

irr::s32 CompositeImage::indexOf(ImageLayout*layout){
	for (irr::u32 i=0;i<list.size();i++)
		if (list[i]==layout)
			return i;
	return -1;
}

CompositeImage::CompositeImage(irr::IrrlichtDevice*d,irr::core::dimension2du s) {
	Size=s;
	device=d;
	device->grab();
	load_mutex=irr::thread::createRecursiveMutex();
	lastThread=0;
	stage=device->getVideoDriver()->createImage(irr::video::ECF_A8R8G8B8,Size);
	texture=0;
}

CompositeImage::~CompositeImage() {
	if (load_mutex->isLocked())
		load_mutex->wait();
	if (stage)
		stage->drop();
	if (texture)
		texture->drop();
	load_mutex->drop();
	device->drop();
}

irr::video::IImage*CompositeImage::getStage(){
	return stage;
}

void CompositeImage::updateTexture(){
	if (!changed){
		return;
	}
	load_mutex->lock();
	for (irr::u32 i=0;i<size();i++){
		//get(i)->getImage()->copyToWithAlpha(stage,get(i)->getPosition(),irr::core::rect<irr::s32>(0,0,get(i)->getImage()->getDimension().Width,get(i)->getImage()->getDimension().Height),irr::video::SColor(0xFFFFFFFF));
		if (get(i)->isVisible() && get(i)->getImage())
			irr::utils::copyImageWithAlpha(get(i)->getImage(),stage,get(i)->getPosition());
	}
	//LOG("stage is done. Save...");
	//device->getVideoDriver()->writeImageToFile(stage,"111.png");
	if (texture){
		texture->drop();
	}
	texture=irr::utils::ImageTexture(stage,device->getVideoDriver(),"test.png");
	changed=false;
	load_mutex->unlock();
}

class tLoader:public irr::thread::ITask{
private:
	CompositeImage*image;
	irr::thread::ITask*task;
public:
	tLoader(CompositeImage*i,irr::thread::ITask*t){
		image=i;
		task=t;
		if (task)
			task->grab();
	}
	virtual void run(){
		image->updateTexture();
		if (task){
			task->run();
			task->drop();
		}
	}
};

bool CompositeImage::updateTexture_unsync(irr::thread::ITask*task){
	if (load_mutex->isLocked())
		return false;
	device->giveTaskAndRunThread(new tLoader(this,task));
	return true;
}

irr::video::ITexture*CompositeImage::getTexture(){
	updateTexture();
	return texture;
}
